package czy.demo.config.shiro;

import org.apache.shiro.biz.utils.WebUtils;
import org.apache.shiro.biz.web.filter.authc.listener.LogoutListener;
import org.apache.shiro.biz.web.servlet.http.HttpStatus;
import org.apache.shiro.session.SessionException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/* 默认登出过滤器 */
@Component
public class DefaultLogoutFilter extends LogoutFilter {

    private static final Logger logger = LoggerFactory.getLogger(DefaultLogoutFilter.class);

    /* 登出监听器 */
    protected List<LogoutListener> logoutListeners;

    /* 预处理，返回过滤器是否应继续 */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response)
            throws Exception {

        Subject subject = getSubject(request, response);

        /* beforeLogout监听 */
        if(getLogoutListeners() != null && getLogoutListeners().size() > 0){
            for (LogoutListener logoutListener : getLogoutListeners()) {
                logoutListener.beforeLogout(subject, request, response);
            }
        }

        Exception ex = null;
        boolean result = false;
        try {
            /* 执行登出 */
            result = this.logout(request, response, subject);
        } catch (Exception e) {
            ex = e;
        }

        /* onFailure，onSuccess回调 */
        if(getLogoutListeners() != null && getLogoutListeners().size() > 0){
            for (LogoutListener logoutListener : getLogoutListeners()) {
                if(ex != null){
                    logoutListener.onFailure(subject, ex);
                }else{
                    logoutListener.onSuccess(subject, request, response);
                }
            }
        }

        if(ex != null){
            throw ex;
        }

        return result;
    }

    protected boolean logout(ServletRequest request, ServletResponse response, Subject subject) throws Exception{

        if (isPostOnlyLogout()) {
            if (!WebUtils.toHttp(request).getMethod().toUpperCase(Locale.ENGLISH).equals("POST")) {
                return onLogoutRequestNotAPost(request, response);
            }
        }


        try {
            subject.logout();
        } catch (SessionException ise) {
            logger.error("Encountered session exception during logout.  This can generally safely be ignored.", ise);
        }


        Map<String, Object> data = new HashMap<String, Object>();
        data.put("code", HttpStatus.SC_SESSION_LOGOUT);
        data.put("status", "logout");
        data.put("message", "Logout Success.");
        WebUtils.writeJSONString(response, data);
        return false;
    }

    public List<LogoutListener> getLogoutListeners() {
        return logoutListeners;
    }

    public void setLogoutListeners(List<LogoutListener> logoutListeners) {
        this.logoutListeners = logoutListeners;
    }


}
